feat: single @guardrail decorator with validator strategy pattern [AL-288]#736
Open
apetraru-uipath wants to merge 1 commit intomainfrom
Open
feat: single @guardrail decorator with validator strategy pattern [AL-288]#736apetraru-uipath wants to merge 1 commit intomainfrom
apetraru-uipath wants to merge 1 commit intomainfrom
Conversation
3747eaa to
04aa96b
Compare
radu-mocanu
reviewed
Mar 30, 2026
| supported_stages: ClassVar[list[GuardrailExecutionStage]] = [] | ||
| """Stages this validator supports. Empty list means all stages are allowed.""" | ||
|
|
||
| def build_built_in_guardrail( |
Collaborator
There was a problem hiding this comment.
nit
Suggested change
| def build_built_in_guardrail( | |
| def built_in_guardrail( |
or
Suggested change
| def build_built_in_guardrail( | |
| def get_built_in_guardrail( |
radu-mocanu
requested changes
Mar 30, 2026
Collaborator
radu-mocanu
left a comment
There was a problem hiding this comment.
code looks clean.
However, I think we should consider moving the implementation to uipath-platform, since uipath guardrails are a platform concern, not necessarily a langchain one
332f7ff to
c73bfc2
Compare
Refactor guardrail decorator layer to use adapter/registry pattern: - Move validator logic (PIIValidator, PromptInjectionValidator, CustomValidator), actions (LogAction, BlockAction), and @guardrail decorator core into uipath-platform; thin re-exports remain in uipath-langchain for backward compat - Add _langchain_adapter.py with LangChainGuardrailAdapter implementing the GuardrailTargetAdapter Protocol; wraps BaseTool, BaseChatModel, StateGraph, CompiledStateGraph; auto-registered on import of uipath_langchain.guardrails - BlockAction now raises GuardrailBlockException (platform); adapter converts to AgentRuntimeError at wrapper boundaries - Update exception guards in middlewares/pii_detection.py and prompt_injection.py to re-raise GuardrailBlockException alongside AgentRuntimeError - Delete decorators/_base.py, decorators/guardrail.py, decorators/validators/* (logic lives in platform); update thin re-exports in decorators/__init__.py Made-with: Cursor Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
c73bfc2 to
f99616d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed?
Replace three type-specific guardrail decorators (
@pii_detection_guardrail,@prompt_injection_guardrail,@deterministic_guardrail) with a single unified@guardrail(validator=..., action=..., name=..., stage=...)decorator using the strategy pattern.New API:
Key changes:
decorators/validators/package withGuardrailValidatorBase,PIIValidator,PromptInjectionValidator,DeterministicValidator@guardraildecorators with different actions or stagesvalidate_scope()/validate_stage()pii_detection.py,prompt_injection.py,deterministic.py) — 100% parity replacement, no backward compat shimsStructuredTool:StructuredTool.ainvoke(no coroutine) delegates toself.invokeviarun_in_executor; overridingainvokein_GuardedToolcaused POST to fire twice (words++++→words++)ruff check --fix+ruff formatFiles:
src/uipath_langchain/guardrails/decorators/guardrail.py— new unified decoratorsrc/uipath_langchain/guardrails/decorators/validators/— 4 new filessrc/uipath_langchain/guardrails/decorators/{pii_detection,prompt_injection,deterministic}.py— deletedsrc/uipath_langchain/guardrails/{__init__,decorators/__init__}.py— updated exportssamples/joke-agent-decorator/graph.py— rewritten to use new APIHow has this been tested?
uv run uipath run agent '{"topic": "money"}'— verified all 3 scopes (AGENT, LLM, TOOL) fire correctly,words++filter applies exactly onceuv run uipath run agent '{"topic": "joke about Andrei Petraru"}'— verified Agent PII (PERSON) blocks withAgentRuntimeErroruv run pytest— all tests pass (2 pre-existing failures for missingbotocore/googleoptional deps, unrelated)uv run ruff check src/uipath_langchain/guardrails/— cleanuv run ruff format— 4 files reformattedAre there any breaking changes?
Ticket
AL-288